<?php

/**
 * Form observer and associated classes
 *
 * A form observer and associated classes for use in form validation.  This
 * code is based on a concept published on DevShed
 * http://www.devshed.com/c/a/PHP/¬
 * Centralizing-the-Validation-of-Data-with-the-Observer-Pattern-in-PHP/
 * and was adapted for PHP4 by Stuart Metcalfe
 *
 * @author Stuart Metcalfe <shoopdev@googlemail.com>
 * @version 1.0
 */

/**
 * FormObserver class
 *
 * Uses an observer pattern to group and monitor DataValidator objects for
 * validating forms.
 */
class FormObserver
{
	var $_notifications;
	var $_fields;
	var $_formVar;
	
	/**
	 * Constructor method
	 *
	 * @access public
	 * @param string $formVar The name of the submit button in your form
	 */
	function FormObserver($formVar)
	{
		$this->_notifications = array();
		$this->_fields = array();
		
		if (sizeof($_POST) > 0)
		{
			$this->_formVar=(isset($_POST[$formVar]));
		}
		
		else
		{
			$this->_formVar=(isset($_GET[$formVar]));
		}
	}
	
	/**
	 * method to add a field to the internal stack
	 *
	 * @access public
	 * @param string $field Field to be added
	 */
	function addField($field)
	{
		$this->_fields[] = $field;
	}
	
	/**
	 * method to add an error to the internal stack
	 *
	 * @access public
	 * @param string $errorMsg Message to be added
	 */
	function addNotification($errorMsg)
	{
		$this->_notifications[]=$errorMsg;
	}
	
	/**
	 * method to check if a field is in the internal stack to be tested
	 *
	 * @access public
	 * @return boolean Is the field in the internal stack to be tested
	 */
	function fieldRequired($field)
	{
		return (in_array($field, $this->_fields));
	}
	
	/**
	 * method to get the internal error stack
	 *
	 * @access public
	 * @return array The internal array of error strings
	 */
	function getErrors()
	{
		return $this->_notifications;
	}
	
	/**
	 * method to see if the form has any errors on the internal stack
	 *
	 * @access public
	 * @return boolean Indicates if the form has validated against all tests
	 */
	function hasErrors()
	{
		return ($this->_formVar && sizeof($this->_notifications)>0);
	}
	
	function isSubmitted()
	{
		return $this->_formVar;
	}
	
	/**
	 * method to see if the form has validated against all DataValidator objects
	 *
	 * @access public
	 * @return boolean Indicates if the form has validated against all tests
	 */
	function isValid()
	{
		if(!$this->isSubmitted() || $this->hasErrors())
		{
			return false;
		}
		
		return true;
	}
}

/**
 * Data validator class
 *
 * Base class to derive other DataValidator object from
 */
class DataValidator
{
	var $_method;
	var $_formObserver;
	
	/**
	 * Constructor method
	 *
	 * Must be a country_id in the countries database table to be valid
	 *
	 * @access public
	 * @param object $formObserver The FormObserver to contain this validator
	 */
	function DataValidator(&$formObserver)
	{
		if (!is_a($formObserver, 'FormObserver'))
		{
			echo 'Invalid object type supplied for DataValidator class';
			return;
		}
		
		$this->_formObserver=&$formObserver;
		
		if (sizeof($_POST) > 0)
		{
			$this->_method=$_POST;
		}
		
		else
		{
			$this->_method=$_GET;
		}
	}
	
	/**
	 * method to notify the formObserver of an error.
	 *
	 * @access public
	 * @param string $errorMsg Message to be passed to the formObserver
	 */
	function notifyObserver($errorMsg)
	{
		$this->_formObserver->addNotification($errorMsg);
	}
	
	/**
	 * validate method to be overridden by subclasses
	 *
	 * Don't forget to call parent::validate() in your overriding method
	 *
	 * @access public
	 * @param string $field Name of the form field
	 * @return boolean Overriding methods must state whether the field validated
	 */
	function validate($field) {
		$this->_formObserver->addField($field);
		return false;
	}
}

?>
